#include "FreeRTOS.h"
#include "FreeRTOS_CLI.h"

#include "cmsis_os.h"
#include <stdio.h>
#include <string.h>

#include "log.h"

#include "stm32f1xx_hal.h"
#include "usart.h"

/* Dimensions the buffer into which input characters are placed. */
#define cmdMAX_INPUT_SIZE 60

/* Dimensions the buffer into which string outputs can be placed. */
#define cmdMAX_OUTPUT_SIZE 1024

/* Dimensions the buffer passed to the recvfrom() call. */
#define cmdSOCKET_INPUT_BUFFER_SIZE 60

extern void vRegisterCLICommands(void);

static char cInputString[cmdMAX_INPUT_SIZE], cOutputString[cmdMAX_OUTPUT_SIZE];

static xQueueHandle hCmdQueue = NULL;
// static xSemaphoreHandle hCmdSem;

void CLI_Task(void const* argument)
{
    uint8_t  cInChar, cInputIndex = 0;
    uint32_t xMoreDataToFollow;

    // hCmdSem = xSemaphoreCreateBinary();
    hCmdQueue = xQueueCreate(20, sizeof(char));

    vRegisterCLICommands();

    // HAL_UART_Receive_IT(&huart1, &tmpChar, 1);
    __HAL_UART_ENABLE_IT(&huart1, UART_IT_RXNE);

    for (;;)
    {
        // LOG("Input char: %X", cInChar);
        if (pdTRUE == xQueueReceive(hCmdQueue, &cInChar, portMAX_DELAY))
        // if (pdTRUE == xSemaphoreTake(hCmdSem, portMAX_DELAY))
        {
            /* The next character in the input buffer. */
            // cInputString[lByte] = cInChar;
            // lByte++;
            fputc(cInChar, NULL);

            /* Newline characters are taken as the end of the command
            string. */
            if (cInChar == '\n' || cInChar == '\r')
            {
                //LOG("Input cmd: %s", cInputString);
                puts("\r\n");
                /* Process the input string received prior to the
                newline. */
                do
                {
                    /* Pass the string to FreeRTOS+CLI. */
                    xMoreDataToFollow = FreeRTOS_CLIProcessCommand(cInputString, cOutputString, cmdMAX_OUTPUT_SIZE);

                    // Put string
                    puts(cOutputString);

                } while (xMoreDataToFollow != pdFALSE); /* Until the command does not generate any more output. */

                /* All the strings generated by the command processing
                have been sent.  Clear the input string ready to receive
                the next command. */
                cInputIndex = 0;
                memset(cInputString, 0x00, cmdMAX_INPUT_SIZE);
                puts("\r\n");
            }
            else
            {
                if (cInChar == '\r')
                {
                    /* Ignore the character.  Newlines are used to
                    detect the end of the input string. */
                }
                else if (cInChar == '\b')
                {
                    /* Backspace was pressed.  Erase the last character
                    in the string - if any. */
                    if (cInputIndex > 0)
                    {
                        cInputIndex--;
                        cInputString[cInputIndex] = '\0';
                    }
                }
                else
                {
                    /* A character was entered.  Add it to the string
                    entered so far.  When a \n is entered the complete
                    string will be passed to the command interpreter. */
                    if (cInputIndex < cmdMAX_INPUT_SIZE)
                    {
                        cInputString[cInputIndex] = cInChar;
                        cInputIndex++;
                    }
                }
            }
        }
    }
}


void SendCLIQueue(uint8_t data)
{
    BaseType_t xHigherPriorityTaskWoken;

    if (hCmdQueue != NULL)
    {
        if (xQueueSendFromISR(hCmdQueue, &data, &xHigherPriorityTaskWoken) == pdTRUE)
        {
            portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
        }
    }
}
